package com.mars.attach.common.utils.file;

import java.io.File;
import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Map.Entry;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.FileCopyUtils;
import org.springframework.util.MultiValueMap;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import com.mars.attach.common.utils.PropertyUtils;
import com.mars.attach.common.utils.RandomUitl;

/**
 * 文件上传工具类，文件上传到独立的服务器中
 */
public class FileUtils extends FileCommonUtil implements Serializable {
	
	private static final long serialVersionUID = 1L;
	
	private static final Logger logger = LoggerFactory.getLogger(FileUtils.class) ;

	/**
	 * 是否生成缩略图
	 */
	public enum Thumbnail {
		yes, no
	}
	
	
	/**
	 * 文件上传
	 * @param path 用户指定上传目录(/aa/bb)
	 * @param thumbnail	是否需要生成缩略图
	 * @param request
	 * @return
	 */
	public static List<FileMeta> upload(String path, Thumbnail thumbnail, HttpServletRequest request) {
		List<FileMeta> list = new ArrayList<FileMeta>() ;
		
		//获取附件的上传路径
		String attachRealPath = PropertyUtils.getValue("AttachRealPath") ;
		//附件上传存放的ROOT目录
		String defaultAttachRootDir = PropertyUtils.getValue("DefaultAttachRootDir") ;
		
		if(null == defaultAttachRootDir || "".equals(defaultAttachRootDir.trim())) {
			throw new RuntimeException("请在upload.properties配置文件中设置文件上传的ROOT目录[UploadRootDir=/uploads]") ;
		}
		
		//文件上传的绝对路径（目录）
		String destDir = FilenameUtils.separatorsToSystem(attachRealPath) ; ;
		
		if(null != path && StringUtils.isNotEmpty(path.trim())) {
			//加上用户指定目录路径
			destDir += FilenameUtils.separatorsToSystem(path + File.separator) ;
		} else {
			destDir += File.separator ;
			path = "" ;
		}
		//创建目录
		if(!FileCommonUtil.checkFileExists(destDir)) {
			FileCommonUtil.createDir(destDir) ;
		}
		
		MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request ;
		
		//取得MultiValueMap集合
		MultiValueMap<String,MultipartFile> multiFileMap = multipartRequest.getMultiFileMap() ;
		Set<Entry<String, List<MultipartFile>>> entrySet = multiFileMap.entrySet() ;
		for (Entry<String, List<MultipartFile>> entry : entrySet) {
			
			//获取MultipartFile集合
			List<MultipartFile> multipartFiles = entry.getValue() ;
			for (MultipartFile multipartFile : multipartFiles) {
				//文件员名
				String originName = multipartFile.getOriginalFilename() ;
				//文件扩展名
				String extension = FilenameUtils.getExtension(originName) ;
				//系统随机生成新的文件名
				String newName = RandomUitl.uuid() + "." + extension ;
				//文件大小
				long size = multipartFile.getSize() ;
				//文件类型
				String contentType = multipartFile.getContentType() ;
				//上传到服务器的路径+文件名称
				String destFilePath = FilenameUtils.separatorsToSystem(destDir + newName) ;
				//文件的相对路径
				String destBasePath = FilenameUtils.separatorsToUnix(defaultAttachRootDir + path + File.separator + newName) ;
				//服务器域名
				String domain = getDomain(request) ;
				//文件URL地址
				String url = domain + destBasePath ;
				//文件删除URL地址
				String delete_url = domain + "?file=" + destBasePath ;
				
				String thumbnail_url = null ;
				
				// TODO 判断是否图片
				//判断是否需要生成缩略图
				if(null != thumbnail && thumbnail.name().equals(Thumbnail.yes)) {
					//图片缩略图URL地址
					thumbnail_url = domain + destBasePath ;
				}
				
				try {
					FileCopyUtils.copy(multipartFile.getBytes(), new File(destFilePath));
				} catch (IOException e) {
					list.add(new FileMeta(false, "文件上传失败")) ;
					logger.error("文件上传失败", e);
				}
				
				list.add(new FileMeta(newName, size, contentType, domain, url, thumbnail_url, delete_url, true, "文件上传成功")) ;
				
				/*
				logger.debug("上传文件成功"
						+ "["
						+ "文件原始名称：{}，"
						+ "文件名称：{}，"
						+ "文件后缀：{}，"
						+ "文件类型：{}，"
						+ "文件大小：{}==>{}，"
						+ "文件存放路径：{}，"
						+ "文件URL：{}，"
						+ "文件删除URL：{}"
						+ "]", originName, newName, extension, contentType, size, FileSizeHelper.getHumanReadableFileSize(size), destFilePath, url, delete_url);
				*/
			}
			
		}
		return list ;
	}
	
	
	/**
	 * 提取服务器URL地址
	 * 
	 * @param request
	 * @return
	 */
	public static String getDomain(HttpServletRequest request) {
		try {
			StringBuffer baseUrl = new StringBuffer();
			String scheme = request.getScheme();
			int port = request.getServerPort();
			
			baseUrl.append(scheme); // http, https
			baseUrl.append("://");
			baseUrl.append(request.getServerName());
			if ((scheme.equals("http") && port != 80) || (scheme.equals("https") && port != 443)) {
				baseUrl.append(':');
				baseUrl.append(request.getServerPort());
			}
			return baseUrl.toString();
		} catch (NullPointerException e) {
			e.printStackTrace(); 
		}
		return null;
	}
}
